#include "Subsystems/BlockBehaviors/SubsystemBlockBehaviors.h"
#include "Subsystems/BlockBehaviors/SubsystemBlockBehavior.hpp"

#include "Managers/BlocksManager.h"

#include "Log.h"
#include "GameSingleton.h"
#include "Utils/Utils.h"

namespace PocketSurvival
{

    static const std::string subsystemName = "BlockBehaviors";
    const std::string& SubsystemBlockBehaviors::getName() const
    {
        return subsystemName;
    }

    std::vector<SubsystemBlockBehavior *> &SubsystemBlockBehaviors::getBlockBehaviors(int32_t contents)
    {
        if(contents >= 0 && contents < 1024)
        {
            return m_blockBehaviorsByContents[contents];
        }
        throw std::logic_error("[SubsystemBlockBehaviors] contents的范围必须是 [0,1024) ");
    }

    void SubsystemBlockBehaviors::addSubsystemBlockBehavior(SubsystemBlockBehavior *blockBehavior)
    {
        if(blockBehavior != nullptr)
        {
            auto it = m_blockBehaviorMap.find(blockBehavior->getName());
            if(it != m_blockBehaviorMap.end())
            {
                throw std::logic_error(fmt::format("方块行为 {} 已经存在，不能重复添加", blockBehavior->getName()));
            }
            m_blockBehaviorMap[blockBehavior->getName()] = blockBehavior;

            Log::Info(fmt::format("添加了方块行为: {}", blockBehavior->getName()));
            const std::vector<int32_t> &handleBlockVec = blockBehavior->getHandleBlocks();
            for(auto it = handleBlockVec.begin(); it != handleBlockVec.end(); ++it)
            {
                Log::Info(fmt::format("使用到的id: {}", *it));
                m_blockBehaviorsByContents[*it].push_back(blockBehavior);
            }
        }
        else
        {
            throw std::logic_error("方块行为不能为nullptr");
        }
    }

    /**
     * @brief 匹配方块行为
     * @param block 需要匹配的方块
    */
    void SubsystemBlockBehaviors::matchBlockBehavior(Block *block)
    {
        if(block->Behaviors.length() == 0)
        {
            return;
        }
        std::string behaviorText = Utils::StringReplace(block->Behaviors, " ", "");
        std::vector<std::string> splitTextVec;
        Utils::StringSplit(behaviorText, ",", splitTextVec);
        for(const std::string &behaviorName : splitTextVec)
        {
            auto it = m_blockBehaviorMap.find(behaviorName);
            if(it != m_blockBehaviorMap.end())
            {
                for(auto behavior : m_blockBehaviorsByContents[block->getIndex()])
                {
                    if(behavior == it->second)
                    {
                        throw std::logic_error(fmt::format("方块 {} 存在相同的方块行为 {}", block->getIndex(), behavior->getName()));
                    }
                }
                m_blockBehaviorsByContents[block->getIndex()].push_back(it->second);
                Log::Info(fmt::format("方块 {} 添加了方块行为 {}", block->getIndex(), it->second->getName()));
            }
            else
            {
                Log::Warn(fmt::format("方块 {} 需要的方块行为 {} 不存在", block->getIndex(), behaviorName));
            }
        }
    }


    void SubsystemBlockBehaviors::load(const nlohmann::json &json)
    {
        // 遍历所有的单例类型，并将方块行为提取出来
        const auto& singletonMap = GameSingleton::singletonPtr->getSingletonMap();
        for(const auto &pair : singletonMap)
        {
            SubsystemBlockBehavior *blockBehaviorPtr = dynamic_cast<SubsystemBlockBehavior*>(pair.second);
            if(blockBehaviorPtr != nullptr)
            {
                addSubsystemBlockBehavior(blockBehaviorPtr);
            }
        }
        
        // 为所有的方块分配方块行为
        for(Block * block : GameSingleton::blocksManager->blocks)
        {
            if(block != nullptr)
            {
                matchBlockBehavior(block);
            }
        }
    }
}